<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<title>vuejs-数量选择器(2层数据结构)</title>
		<style type="text/css">
			* {
				padding: 0;
				margin: 0;
				box-sizing: border-box;
				font-size: 16px;
			}
			
			a {
				text-decoration: none;
				color: #333;
			}
			
			.clearfix:after {
				content: ".";
				visibility: hidden;
				display: block;
				height: .1px;
				font-size: .1em;
				line-height: 0;
				clear: both;
			}
			
			.quantity-selector {
				margin: 0 auto;
				width: 8.571rem;
				line-height: 30px;
				border: 1px solid #d1d6e4;
				border-radius: 3px;
			}
			
			.quantity-selector .reduce,
			.quantity-selector .add {
				float: left;
				width: 33.33%;
				border-right: 1px solid #d1d6e4;
				text-align: center;
				cursor: pointer;
			}
			
			.quantity-selector .number {
				float: left;
				width: 33.33%;
				height: 30px;
				border: none;
				padding-left: 10px;
				text-align: center;
			}
			
			.quantity-selector .add {
				border-left: 1px solid #d1d6e4;
				border-right: none;
			}
			
			.quantity-selector .disable {
				color: #d2d2d2;
				cursor: default;
			}
			
			label {
				cursor: pointer;
			}
			
			.choose-all {
				margin-left: 20px;
			}
			/*店铺开始*/
			
			.store-item {
				width: 600px;
				margin: 30px auto;
			}
			
			.store-item th {
				height: 40px;
				background: #d2d2d2;
				-webkit-text-stroke: 1px #ff7500;
				font-size: 18px;
			}
			
			.store-item td {
				height: 60px;
				text-align: center;
			}
			
			.cal-store-box {
				text-align: right;
			}
			
			.store-footer {
				width: 600px;
				margin: 50px auto;
				display: flex;
				justify-content: space-between;
				align-items: center;
			}
			/*店铺结束*/
		</style>
	</head>

	<body>
		<div class="store-item" v-for="(index1, item) in goodsObj">
			<p>
				<span v-html="item.name"></span>
				<label class="choose-all">
      <input type="checkbox" name="all" v-on:click="chooseShopGoods(index1)" v-model="item.checked" />
      <span>全选</span>
    </label>
			</p>
			<table class="store-item">
				<col width="10%"></col>
				<col width="15%"></col>
				<col width="15%"></col>
				<col width="10%"></col>
				<col width="40%"></col>
				<col width="10%"></col>
				<thead class="thead">
					<tr>
						<th>选择</th>
						<th>商品</th>
						<th>单价</th>
						<th>运费</th>
						<th>数量</th>
						<th>操作</th>
					</tr>
				</thead>
				<tbody>
					<tr v-for="(index, data) in item.list">
						<td>
							<input type="checkbox" name="all" v-model="data.checked" v-on:click="choose(index1, index)" />
						</td>
						<td>
							<p><span v-html="data.name"></span></p>
						</td>
						<td v-html="(data.price).toFixed(2)"></td>
						<td v-html="(data.fare).toFixed(2)"></td>
						<td>
							<div class="quantity-selector clearfix">
								<span class="reduce" v-on:click="numChange(index1, $index, -1)" v-bind:class="{ 'disable' : data.num==1 }">－</span>
								<input type="number" v-bind:value="data.num" class="number" v-bind:data-realStock="data.realStock" v-on:keyUp="numEntry(index1, $index)" v-on:keyDown="numEntry(index1, $index)" v-model="data.num" />
								<span class="add" v-on:click="numChange(index1, $index, 1)" v-bind:class="{ 'disable' : data.num==data.realStock }">＋</span>
							</div>
						</td>
						<td>
							<a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" v-on:click="delGoods(index1, index)">删除</a>
						</td>
					</tr>
				</tbody>
			</table>
			<div class="cal-store-box">
				<p>店铺总运费: <span v-html="calEveryFare(index1)"></span></p>
				<p>店铺商品总金额: <span v-html="calEveryStore(index1)"></span></p>
			</div>
		</div>

		<div class="store-footer">
			<label>
    <input type="checkbox" v-on:click="chooseAllGoods($event)" v-model="allChecked" />
    <span>全选</span>
  </label>
			<div class="cal-box">
				<p>商品总运费:<span v-html="totalFare.toFixed(2)"></span></p>
				<p>商品总金额:<span v-html="totalMoney.toFixed(2)"></span></p>
			</div>
		</div>

		<script src="http://cdn.bootcss.com/vue/1.0.7/vue.js"></script>
		<script>
			var goodsObj = [{
					name: '大胖的店',
					checked: false,
					list: [{
							name: '麻辣二胖',
							price: 23.00,
							realStock: 10,
							fare: 1.5,
							num: 1,
							checked: false,
						},

						{
							name: '香辣二胖',
							price: 21.00,
							realStock: 2,
							fare: 1.5,
							num: 2,
							checked: false,
						},

						{
							name: '红烧二胖',
							price: 88.00,
							realStock: 8,
							fare: 1.5,
							num: 4,
							checked: false,
						}
					]
				},

				{
					name: '二胖的店',
					checked: false,
					list: [{
							name: '漂亮的裙子',
							price: 166.00,
							realStock: 10,
							fare: 2,
							num: 1,
							checked: false,
						},

						{
							name: '漂亮的短袖',
							price: 188.00,
							realStock: 2,
							fare: 1.5,
							num: 2,
							checked: false,
						},

						{
							name: '漂亮的鞋子',
							price: 299.00,
							realStock: 1,
							fare: 3,
							num: 1,
							checked: false,
						}
					]
				},

				{
					name: '胖胖的店',
					checked: false,
					list: [{
							name: '福满多',
							price: 3.00,
							realStock: 10,
							fare: .5,
							num: 10,
							checked: false,
						},

						{
							name: '精品卫龙',
							price: 1.50,
							realStock: 2,
							fare: 2,
							num: 2,
							checked: false,
						},

						{
							name: '周长江',
							price: 2.50,
							realStock: 3,
							fare: 5,
							num: 2,
							checked: false,
						}
					]
				},
			];
			var vue = new Vue({
				el: 'body',
				data: {
					goodsObj: goodsObj,
					totalMoney: 0,
					totalFare: 0,
					allChecked: false
				},
				ready: function() {},
				methods: {

					// 全部商品全选
					chooseAllGoods: function() {
						var flag = true;
						if(this.allChecked) {
							flag = false;
						}
						for(var i = 0, len = this.goodsObj.length; i < len; i++) {
							this.goodsObj[i]['checked'] = flag;
							var list = this.goodsObj[i]['list'];
							for(var k = 0, len1 = list.length; k < len1; k++) {
								list[k]['checked'] = flag;
							}
						}
						this.allChecked = !this.allChecked;
						this.calTotalMoney();
						this.calTotalFare();
					},

					// 每个店铺全选
					chooseShopGoods: function(index) {
						var list = this.goodsObj[index]['list'],
							len = list.length;
						if(this.goodsObj[index]['checked']) {
							for(var i = 0; i < len; i++) {
								list[i]['checked'] = false;
							}
						} else {
							for(var i = 0; i < len; i++) {
								list[i]['checked'] = true;
							}
						}
						this.goodsObj[index]['checked'] = !this.goodsObj[index]['checked'];

						// 判断是否选择所有商品的全选
						this.isChooseAll();

						this.cal(index);
					},

					// 单个选择
					choose: function(index1, index) {
						var list = this.goodsObj[index1]['list'],
							len = list.length;
						if(list[index]['checked']) {
							this.goodsObj[index1]['checked'] = false;
							this.allChecked = false;
							list[index]['checked'] = !list[index]['checked'];
						} else {
							list[index]['checked'] = !list[index]['checked'];

							// 判断是否选择当前店铺的全选
							var flag = true;
							for(var i = 0; i < len; i++) {
								if(list[i]['checked'] == false) {
									flag = false;
									break;
								}
							}
							flag == true ? this.goodsObj[index1]['checked'] = true : this.goodsObj[index1]['checked'] = false;
						}

						// 判断是否选择所有商品的全选
						this.isChooseAll();

						this.cal(index);
					},

					// 判断是否选择所有商品的全选
					isChooseAll: function() {
						var flag1 = true;
						for(var i = 0, len = this.goodsObj.length; i < len; i++) {
							if(this.goodsObj[i]['checked'] == false) {
								flag1 = false;
								break;
							}
						}
						flag1 == true ? this.allChecked = true : this.allChecked = false;
					},

					// 商品数量控制
					numChange: function(index1, index, numChange) {
						var goods = this.goodsObj[index1]['list'][index],
							oThis = this;
						if(numChange == 1) {
							goods.num++;
						} else if(numChange == -1) {
							goods.num--;
						}

						if(goods.num <= 1) {
							goods.num = 1;
						}

						if(goods.num >= goods.realStock) {
							goods.num = goods.realStock;
						}

						this.cal(index);
					},

					// 用户填写容错处理
					numEntry: function(index1, index) {
						var goods = this.goodsObj[index1]['list'][index];
						if(goods.num <= 1) {
							goods.num = 1;
						}

						if(goods.num > goods.realStock) {
							goods.num = goods.realStock;
						}
						this.cal(index);
					},

					// 计算每个店铺的商品总额
					calEveryStore: function(index) {
						var everyStoreMoney = 0,
							list = this.goodsObj[index]['list'];
						list.forEach(function(item, index, arr) {
							if(list[index]['checked']) {
								everyStoreMoney += parseFloat(item.price) * parseFloat(item.num);
							}
						});
						return everyStoreMoney.toFixed(2);
					},

					// 计算每个店铺的运费总额
					calEveryFare: function(index) {
						var everyStoreFare = 0,
							list = this.goodsObj[index]['list'];
						list.forEach(function(item, index, arr) {
							if(list[index]['checked']) {
								everyStoreFare += parseFloat(item.fare) * parseFloat(item.num);
							}
						});
						return everyStoreFare.toFixed(2);
					},

					// 计算商品总金额
					calTotalMoney: function() {
						var oThis = this;
						this.totalMoney = 0;
						for(var i = 0, len = this.goodsObj.length; i < len; i++) {
							var list = this.goodsObj[i]['list'];
							list.forEach(function(item, index, arr) {
								if(list[index]['checked']) {
									oThis.totalMoney += parseFloat(item.price) * parseFloat(item.num);
								}
							});
						}
					},

					// 计算商品总运费
					calTotalFare: function() {
						var oThis = this;
						this.totalFare = 0;
						for(var i = 0, len = this.goodsObj.length; i < len; i++) {
							var list = this.goodsObj[i]['list'];
							list.forEach(function(item, index, arr) {
								if(list[index]['checked']) {
									oThis.totalFare += parseFloat(item.fare) * parseFloat(item.num);
								}
							});
						}
					},

					// 计算方法集合
					cal: function(index) {
						this.calEveryStore(index);
						this.calEveryFare(index);
						this.calTotalMoney();
						this.calTotalFare();
					},

					// 删除操作
					delGoods: function(index1, index) {
						console.log(index1);
						console.log(index);
						this.goodsObj[index1]['list'].splice(index, 1);
						this.cal(index);
					}
				}
			})
		</script>
	</body>

</html>